var
  CharLoc:integer; {Global variable, initially zero}

macro 'Save using Time as Name';
{Note: Colons are not allowed in file names.}
var
  year,month,day,hour,minute,second,DayOfWeek:integer;
begin
  GetTime(year,month,day,hour,minute,second,DayOfWeek);
  SaveAs(year:4,'-',month:2,'-',day:2,
         '/',hour:2,'-'minute:2,'-',second:2);
end;


macro 'Open with selection [O]';
begin
  if nPics>0 then KillRoi; {Save Selection}
  Open('');                {Prompt for file name}
  RestoreROI;              {Transfer selection to new window}
end;


macro 'Save All';
{
Saves all currently open images in a folder using '001', '002', etc.
as the file names. The save file dialog box will be displayed once
(and only once) so that you can specify the folder to save the files in.
Leave the file name blank(e.g. SaveAs('')) to get a dialog box for each file.
}
var
  n:integer;
begin
  RequiresVersion(1.45);
  for n:=1 to nPics do begin
    SelectPic(n);
    SaveAs(n:3);
    {Export(n:3);}
  end;
end;


macro 'Import FITS';
{
Imports 8 and 16-bit FITS images. Refer to "FITS:A Flexible Image
Transport System", Astronomy and Astrophysics Supplement
Series 44, 1981, 363-370.
}
var
  width,height,offset,HdrPid:integer;
  recsize,maxrecs,maxlines,loc,i,line:integer;
  BitPix,str:string;
begin
  RequiresVersion(1.52);
  recsize:=2880;
  maxrecs:=10; {Must be increased to handle headers longer than 360 lines.}
  maxlines:=(recsize*maxrecs)/80;
  width:=recsize; 
  height:=maxrecs;
  offset:=0;
  SetImport('8-bit'); 
  SetCustom(width,height,offset);
  Import(''); {Read in header as an image, prompting for the file name.}
  HdrPid:=PidNumber;
  BitPix:=Concat(chr(GetPixel(108,0)),chr(GetPixel(109,0)));
  if (BitPix<>' 8') and (BitPix<>'16') then begin
    PutMessage('This macro only reads 8 and 16-bit FITS files');
    SelectPic(HdrPid);
    Dispose;
    exit;
  end;
  str:=concat(chr(GetPixel(266,0)), chr(GetPixel(267,0)),
    chr(GetPixel(268,0)), chr(GetPixel(269,0)));
  width:=StringToNum(str);
  str:=concat(chr(GetPixel(346,0)), chr(GetPixel(347,0)),
    chr(GetPixel(348,0)), chr(GetPixel(349,0)));
  height:=StringToNum(str);
  loc:=0;
  line:=0;
  repeat
    str:='';
    for i:=1 to 3 do begin
       str:=concat(str,chr(GetPixel(loc mod recsize, loc div recsize)));
       loc:=loc+1;
    end;
    loc:=loc+77; {Skip to end of line}
    line:=line+1;
  until (line>=maxlines) or (str='END');
  SelectPic(HdrPid);
  Dispose;
  offset:=recsize+recsize*((line*80) div recsize);
  if BitPix=' 8'
    then SetImport('8-bit')
    else SetImport('16-bit Signed; Calibrate; Autoscale');
  SetCustom(width,height,offset);
  Import('');  {No prompt this time; Import remembers the name.}
  if BitPix=' 8' then Invert;
  FlipVertical;
end;

macro 'Display FITS Header';
var
  i,j,loc:integer;
  HdrPid,RecordSize,maxlines,line:integer;
  MaxRecords:integer;
  wname,str:string;
begin
  RequiresVersion(1.53);
  RecordSize:=2880;
  MaxRecords:=10;
  maxlines:=(RecordSize*MaxRecords)/80;
  SetImport('8-bit'); 
  SetCustom(RecordSize,10,0);
  Import(''); {Read in header as an image, prompting for the file name.}
  HdrPid:=PidNumber;
  SetFont('Monaco');
  SetFontSize(9);
  wname:=concat(WindowTitle,' Header');
  NewTextWindow(wname,500,500);
  loc:=0;
  line:=1;
  repeat
    ChoosePic(HdrPid);
    str:='';
    for j:=1 to 80 do begin
       str:=concat(str,chr(GetPixel(loc mod RecordSize, loc div RecordSize)));
       loc:=loc+1;
    end;
    SelectWindow(wname);
    writeln(str);
    line:=line+1;
  until (line>maxlines) or (pos('END',str)=1);
  SelectPic(HdrPid);
  Dispose;
 end;


macro 'Import Image TIFF File';
{
As an example of how to import a foreign file format, this macro reads
the TIFF files created by Image. The format of an Image TIFF file
is described in Appendix E of the Image manual.
}  
var
  width,height,offset:integer;
begin
  width:=768; 
  height:=1;
  offset:=0;
  SetImport('8-bit'); 
  SetCustom(width,height,offset);
  Import(''); {Read in header as an image, prompting for the file name.}
  if not ((GetPixel(0,0)=77) and (GetPixel(0,0)=77)) then begin  {'MM'}
    PutMessage('This is not a TIFF file.');
    SelectPic(nPics); Dispose;
    exit;
  end;
  width := (GetPixel(30,0)*256) + GetPixel(31,0);
  height := (GetPixel(42,0)*256) + GetPixel(43,0);
  SelectPic(nPics);  {The ID of the last window opened is equal to nPics.}
  Dispose;
  offset:=768;
  SetCustom(width,height,offset);
  Import('');  {No prompt this time; Import remembers the name.}
end;


macro 'Import Multiple Images per File';
{
Imports a series of 256x256 images contained in a single file, in this
case an NIH Image stack with an arbitrary number of 256x256 slices.
}
var
  offset,i,PicSize,HdrSize,width,height:integer;
begin
  HdrSize:= 768;
  width:= 256;
  height:=256;
  PicSize:=width*height;
  offset:=HdrSize;
  SetImport('8-bit');
  for I:=1 to 100 do begin  {Macro will terminate at eof}
    SetCustom(width,height,offset);
    Import('');
    offset:=offset+PicSize;
  end;
end;


macro 'Import 3D PET';
var
  HdrSize,width,height:integer;
begin
  HdrSize:= 0;
  width:= 128;
  height:=128;
  SetImport('8-bit');
  SetCustom(width, height, HdrSize, 100);
  Import('');
end;


macro 'Convert Files';
{
Converts a set of raw data files(all in the same folder) with names
in the form raw.001, raw.002, etc to TIFF or PICT.  As long as the
converted files are saved in the same folder, you should
only see two file dialog boxes(one for the first Import and one for
the first SaveAs).
}
Var
  i,nFiles:integer;
begin
  nFiles:=GetNumber('Number of files:',5);
  for i:=1 to nFiles do begin
    Import('raw.',i:3);
    SetPicName('file',i:3);
    SaveAs;
    Dispose;
  end;
end;


macro 'Import IPLab File';
var
   width,height,offset:integer;
begin
   width:=100; 
   height:=1;
   offset:=0;
   SetImport('8-bit'); 
   SetCustom(width,height,offset);
   Import(''); {Read in header as an image, prompting for file name.}
   width := (GetPixel(8,0)*256) + GetPixel(9,0);
   height := (GetPixel(12,0)*256) + GetPixel(13,0);
   Dispose;  
   offset:=2120;  {The IPLab offset}
   SetImport('16-bit Signed; Calibrate; Autoscale');
   SetCustom(width,height,offset);
   Import('');  {No prompt this time; Import remembers the name.}
end;


procedure ShowBioRadInfo(InfoOffset: integer);
{Displays the contents of the 480(?) byte header at}
{the end of Biorad MRC 600 Z Series files.}
var
  MaxInfoSize,offset:integer;
  ch, title:string;
begin
  MaxInfoSize:=480;
  SetCustom(MaxInfoSize, 1, InfoOffset);
  SetImport('8-bit'); {Don't invert}
  Import('');
  GetRow(0,0,MaxInfoSize);
  Dispose;
  SaveState;
  title := concat(WindowTitle, '.Info');
  NewTextWindow(title, 450, 150);
  SetCursor('Watch');
  SetFont('Monaco');
  SetFontSize(12);
  for i:=0 to MaxInfoSize-1 do begin
    offset:=i mod 96;
    if offset=0 then writeln;
    ch:=chr(LineBuffer[i]);
    if (offset=2) and (ord(ch)=0) then exit;
    if (offset>=16) and (offset<=95) and (ord(ch)>=32) and (ord(ch)<=126)
      then write(ch);
  end;
  RestoreState;
end;


macro 'Import Biorad MRC 600 Z Series';
{
Imports a Z series(multiple images per file) from a Biorad MRC 600
confocal microscope.  The width, height and number of images are
extracted from the first 3 16-bit word in the 76 byte header and
the file name is extracted from bytes 18-23 of the header. This macro
does not read merged pseudocolored BioRad files. Note that the Undo
and Clipboard buffers must be set to 384K to work with the typical
768x512 Biorad images.
}
var
  width,height,nImages,offset,hdrsize,i,start,picsize:integer;
begin
  RequiresVersion(1.50);
  width:=512; 
  height:=1;
  offset:=0;
  SetImport('8-bit'); 
  SetCustom(width,height,offset);
  Import(''); {Read header}
  GetPicSize(width,height);
  if (width<>512) or (height<>1) then begin
    Dispose;
    PutMessage('Please to not change width, height, etc. in the Import dialog box.');
    exit;
  end;
  width:=GetPixel(0,0)+GetPixel(1,0)*256;
  height:=GetPixel(2,0)+GetPixel(3,0)*256;
  nImages:=GetPixel(4,0)+GetPixel(5,0)*256;
  Dispose;
  hdrsize:= 76;
  picsize:=width*height;
  if (width<128) or (width>2048) or (height<128) or (height>2048) or (nImages<1) or (nImages>256) then begin
    PutMessage('This does not seem to be a Biorad MRC 600 Z Series file.');
    exit;
  end;
  start:=GetNumber('Starting image:',1);
  offset:=HdrSize+(start-1)*PicSize;
  SetImport('8-bit, Invert');
  SetCustom(width,height,offset,nimages);
  Import('');
  ShowBioRadInfo(HdrSize + nImages * width * height);
end;


macro 'Import from IBAS';
var
   width,height,offset:integer;
begin
   width:=128; 
   height:=1;
   offset:=0;
   SetImport('8-bit'); 
   SetCustom(width,height,offset);
   Import(''); {Read in header as an image, prompting for file name.}
   width := (GetPixel(7,0)*256) + GetPixel(6,0);
   height := (GetPixel(9,0)*256) + GetPixel(8,0);
   Dispose(nPics);  {The ID of the last window opened = nPics.}
   offset:=128;  {The IBAS offset}
   SetImport('8-bit; Calibrate; Autoscale');
   SetCustom(width,height,offset);
   Import('');  {No prompt this time; Import remembers the name.}
   Invert
   SetScaling ('Bilinear');
   SetScaling ('New Window');
   ScaleAndRotate (0.80, 1.0, 0);
end;


macro 'Import 64x64x64x16-bit SPECT Image';
{Imports a 64x64x64x16-bit headerless SPECT image into a stack.}
var
  width,height,nImages,hdrsize:integer;
begin
  RequiresVersion(1.50);
  width:=64;
  height:=64;
  nImages:=64;
  HdrSize:= 0;
  SetImport('16-bit Unsigned, Swap Bytes');
  {SetImportMinMax(0,2500);} {Uncomment to fix scale}
  SetCustom(width,height,HdrSize,nImages);
  Import('');
 end;


macro 'Import 8-bit 3D Image';
var
  width,height,offset,nImages:integer;
begin
  RequiresVersion(1.50);
  width:=GetNumber('Width:',256);
  height:=GetNumber('Height:',256);
  nImages:=GetNumber('Depth(number of slices):',128);
  offset:=GetNumber('Offset(header size):',0);
  SetImport('8-bit'); 
  SetCustom(width,height,offset,nImages);
  Import('');
end;


macro 'Open with scale set to 100 pixels/mm [S]';
{Example of a way to open images and have the}
{spatial scale always set the same way.}  
begin
  Open('');           {or Import('')}
  SetScale(100,'mm'); {Change as needed}
end;


macro 'Load Synergy Image';
begin
   SetImport('8-bit'); 
   SetCustom(512,480,16384);
   Import('');
   ChangeValues(0,0,1);
   ChangeValues(255,255,254);
   SetPalette('Rainbow');
end;


macro 'Import Siemens 3D MRI';
begin
  RequiresVersion(1.50);
  SetImport('16-bit Signed, Swap Bytes');
  {SetImportMinMax(0,3000);} {Remove comments to fix scale}
  SetCustom(256,256,0,127);
  Import('');
end;


macro 'Import LUT';
{Imports a 256 x 3 x 8-bit look-up table located 'offset'
 bytes from the beginning of a file. Use an offset of 32 for
 LUTs created using Image's Save As command and an
 offset of 0 for Exported LUTs.}
}  
var
  offset,i:integer;
begin
  offset:=0; {Use 32 for LUTs created using Save As}
  SetImport('8-bit'); 
  SetCustom(256,3,offset);
  Import(''); {Read LUT as an image}
  for i:=0 to 255 do begin
    RedLut[i]:=GetPixel(i,0);
    GreenLut[i]:=GetPixel(i,1);
    BlueLut[i]:=GetPixel(i,2);
  end;
  UpdateLUT;
end;

macro 'Open List of Files';
var
  width,height:integer;
  name,ch:string;
begin
  width:=256;
  height:=3;
  SetCustom(width,height,0);
  Import('File List'); {Read text as an image}
  repeat
    name:='';
    repeat
       ch:=chr(GetPixel(CharLoc mod width,CharLoc div width));
       if ch>=chr(32) then begin
         name:=concat(name,ch);
       end;
       CharLoc:=CharLoc+1;
     until (ch=13) or (CharLoc>=width*height);
     ShowMessage(name);
     wait(1);
  until (name='') or (CharLoc>=width*height);
end;

macro 'File processing test';
begin
  Open('hd400:images:image001');
  Invert;
  Save;
  Close;
  Open('hd400:images:image002');
  Invert;
  Save;
  Close;
  Open('hd400:images:image003');
  Invert;
  Save;
  Close;
end;

macro 'Batch Processing Example';
{
Reads from disk and processes a set of images too large to
simultaneously fit in memory. The image names names must be
in the form 'image001', 'image002', ..., but this can be changed.
}
var
  i:integer;
begin
  for i:=1 to 1000 do begin
      open('image',i:3);
     {process;}
      save;
      close;
   end;
end;


macro 'Export Non-Rectangular ROI';
var
  left,top,width,height:integer;
  pid1,pid2:integer;
begin
  GetRoi(left,top,width,height);
  if width=0 then begin
     PutMessage('Non-rectangular selection required.');
     exit;
  end;
  pid1:=PidNumber;
  SetNewSize(width,height);
  MakeNewWindow('Temp');
  pid2:=PidNumber;
  SelectPic(pid1);
  Copy;
  SelectPic(pid2);
  Paste;
  Export; {or SaveAs}
end;


macro 'Import MCID';
begin
  SetImport('MCID'); 
  Import(''); 
end;


macro 'Import Series of Files';
Var
  i,first,last:integer;
  width, height, offset:integer;
begin
  width := 512;
  height := 512;
  offset := 0;
  first:=round(GetNumber('First file number:',1));
  last:=round(GetNumber('Last file number:',999));
  SetImport('Custom; 8-bits; Invert');
  SetCustom(width,height,offset);
  for i:=first to last do
    Import('IMG',i:4, '.CASTRO11');
end;



macro 'File Paths Demo';
{Demonstrates the new GetPath() and GetFileInfo() macro functions.}
var
  wPath, sPath, pPath: string;
  name, FullPath, FileType, folder: string;
  FileSize: integer;
begin
  name := WindowTitle; {Grab name before before opening window} 
  wPath := GetPath('window'); {Grab path before before opening window}
  sPath := GetPath('startup');
  pPath := GetPath('pref');
  SaveState;
  SetFont('Geneva');
  SetFontSize(12);
  NewTextWindow('Paths Demo');

  if wPath = '' then begin
     writeln('No opened image or text window');
     writeln
  end else begin
     writeln;
     FullPath := concat(wPath, name);
     writeln('Active window path = "', FullPath, '"');
     GetFileInfo(FullPath, FileType, FileSize);
     writeln('File type = "', FileType, '"');
     writeln('File size = ', FileSize:1);
     writeln;
  end;
  writeln('Startup path = "', sPath, '"');
  writeln('Preferences path = "', pPath, '"');

		writeln;
  name := 'Image Prefs';
  FullPath := concat(GetPath('pref'), name);
  GetFileInfo(FullPath, FileType, FileSize);
  if FileSize < 0 then
     writeln('"', name, '" not found in Preferences folder')
  else
     writeln('The file "', name,'" (type="', FileType,
     '", size=', FileSize:1, ') was found in Preferences folder.');

  writeln;
  name := 'image1.tif';
  folder := 'Images';
  FullPath := concat(GetPath('startup'), folder, ':', name);
  GetFileInfo(FullPath, FileType, FileSize);
  if FileSize < 0 then
     writeln('The file "', name, '" was not found in the "',
       folder, '" folder in NIH Image folder.')
  else begin
					writeln('Opening the file "', FullPath, '"');
     open(FullPath);
  end;

  RestoreState;
end;


function GetName(ListName: string; i: integer): string;
{Returns the the ith line from a text file that has been
read into a one line image named 'ListName'.}
var
   loc, ch: integer;
   name: string;
begin
  SelectWindow(ListName);
  loc := -1;
  for i := 2 to i do
     repeat
       loc := loc + 1;
       ch := GetPixel(loc, 0)
     until ch < 32; {return or linefeed}
  name := '';
  repeat
     loc := loc + 1;
     ch := GetPixel(loc, 0);
     if ch >= 32 then
       name := concat(name, chr(ch));
  until ch < 32;
  GetName := name;
end;


Macro 'Open Files From List...';
{Opens a series of files from a list stored in a text file.}
var
   path, FileType, ListName, ImageName: string;
   FileSize, i: integer;
begin
  ListName := 'file-list.txt';
  path := concat(GetPath('startup'), ListName);
  GetFileInfo(path, FileType, FileSize);
  if FileSize < 0 then begin
     PutMessage('The file "', ListName, '" could not be found in the same folder as NIH image.');
     exit;
  end;
  SetImport('8-bit');
  SetCustom(FileSize, 1, 0);
  Import(path);
  for i := 1 to 1000 do begin
    ImageName := GetName(ListName, i);
    if ImageName = '' then begin
        SelectWindow(ListName);
        close;
        exit;
     end;
     open(ImageName);
     {process image}
     wait(1);
     close;
  end;
end;

